//
//  Event.Base.swift
//  Utility
//
//  Created by 何海涛 on 2017/5/27.
//  Copyright © 2017年 何海涛. All rights reserved.
//

import Foundation

/// 多播协议。
/// 多播：在发送者和每一接收者之间实现一对多的消息传递。
/// - Note: 如果发送者同时给多个的接收者传输相同的数据，也只需复制一份的相同数据。这也就是说`引用类型`是参数传递的最佳选择。
public protocol IMulticast {
    
    associatedtype Handler: AnyObject
    
    /// 多播消息发送方法。
    ///
    /// - Parameter thunk: 消息转换程序（闭包）
    /// - Parameter handler: 消息接收者
    func invoke(_ thunk: (_ handler: Handler)->Void)
}

/// 类型包装器，用来解决想构建`IMulticast`,`IEvent`数组的问题。
/// - Note: 在swift中，并不能创建[IMulticast]或者[IEvent]。使用该包装器可以创建[AnyMulticast]
public struct AnyMulticast<THandler: AnyObject>: IMulticast {
    
    private let _invoke: ((THandler)->Void)->Void
    
    public init<Multicast: IMulticast>(_ base: Multicast) where Multicast.Handler == THandler {
        _invoke = base.invoke
    }
    
    public func invoke(_ thunk: (THandler)->Void) {
        _invoke(thunk)
    }
}

//@objc protocol IDemo {
//    func doSth()
//}
//class ConcretDemoA: IDemo {
//    func doSth() {
//        print("ConcretDemoA")
//    }
//}
//class ConcretDemoB: IDemo {
//    func doSth() {
//        print("ConcretDemoB")
//    }
//}
//class ConcretDemoC: IDemo {
//    func doSth() {
//        print("ConcretDemoC")
//    }
//}
//
//class EraserDemo {
//    
//    static func run() {
//        var events1 = Event<IDemo>.init()
//        events1 += ConcretDemoA()
//        events1 += ConcretDemoB()
//        var events2 = Event<IDemo>.init()
//        events2 += ConcretDemoC()
//        let events: [AnyMulticast<IDemo>] = [AnyMulticast(events1),AnyMulticast(events2)]
//        for e in events {
//            e.invoke({ $0.doSth() })
//        }
//    }
//}
